﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Globalization;

namespace SmartMathLibrary.Storage
{
    /// <summary>
    /// This struct represents a simple storage point in a plane space.
    /// </summary>
    [Serializable]
    public struct StoragePoint : IStoragePoint, IComparable
    {
        /// <summary>
        /// The x value of the point.
        /// </summary>
        private double x;

        /// <summary>
        /// The y value of the point.
        /// </summary>
        private double y;

        /// <summary>
        /// Initializes a new instance of the <see cref="StoragePoint"/> struct.
        /// </summary>
        /// <param name="x">The x value of the point.</param>
        /// <param name="y">The y value of the point.</param>
        public StoragePoint(double x, double y)
        {
            this.x = x;
            this.y = y;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="StoragePoint"/> struct.
        /// </summary>
        /// <param name="point">The point to convert.</param>
        public StoragePoint(Point point)
        {
            this.x = point.X;
            this.y = point.Y;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="StoragePoint"/> struct.
        /// </summary>
        /// <param name="point">The point to clone.</param>
        public StoragePoint(StoragePoint point)
        {
            this.x = point.X;
            this.y = point.Y;
        }

        /// <summary>
        /// Gets or sets the x value of the storage point.
        /// </summary>
        /// <value>The x value of the storage point.</value>
        public double X
        {
            get { return x; }
            set { x = value; }
        }

        /// <summary>
        /// Gets or sets the y value of the storage point.
        /// </summary>
        /// <value>The x value of the storage point.</value>
        public double Y
        {
            get { return y; }
            set { y = value; }
        }

        /// <summary>
        /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
        /// </summary>
        /// <param name="obj">An object to compare with this instance.</param>
        /// <returns>
        /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
        /// Value
        /// Meaning
        /// Less than zero
        /// This instance is less than <paramref name="obj"/>.
        /// Zero
        /// This instance is equal to <paramref name="obj"/>.
        /// Greater than zero
        /// This instance is greater than <paramref name="obj"/>.
        /// </returns>
        /// <exception cref="T:System.ArgumentException">
        /// 	<paramref name="obj"/> is not the same type as this instance.
        /// </exception>
        public int CompareTo(Object obj)
        {
            if (obj is StoragePoint)
            {
                if (this.x == ((StoragePoint) obj).X)
                {
                    return 0;
                }

                if (this.x < ((StoragePoint) obj).X)
                {
                    return -1;
                }

                if (this.x > ((StoragePoint) obj).X)
                {
                    return 1;
                }
            }

            return 0;
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="a">The first StoragePoint.</param>
        /// <param name="b">The second StoragePoint.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(StoragePoint a, StoragePoint b)
        {
            if (((object) a == null) || ((object) b == null))
            {
                return false;
            }

            return ((a.X == b.X) && (a.Y == b.Y));
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="a">The first StoragePoint.</param>
        /// <param name="b">The second StoragePoint.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(StoragePoint a, StoragePoint b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Indicates whether this instance and a specified object are equal.
        /// </summary>
        /// <param name="obj">Another object to compare to.</param>
        /// <returns>
        /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            if ((object) obj == null)
            {
                return false;
            }

            if (obj is StoragePoint)
            {
                return ((((StoragePoint) obj).X == this.x) && (((StoragePoint) obj).Y == this.y));
            }

            return false;
        }

        /// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
        /// <returns>
        /// A 32-bit signed integer that is the hash code for this instance.
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Returns the fully qualified type name of this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> containing a fully qualified type name.
        /// </returns>
        public override string ToString()
        {
            return this.ToString(CultureInfo.CurrentCulture);
        }

        /// <summary>
        /// Returns the fully qualified type name of this instance.
        /// </summary>
        /// <param name="provider">The format provider to define the requested culture.</param>
        /// <returns>
        /// A <see cref="T:System.String"/> containing a fully qualified type name.
        /// </returns>
        public string ToString(IFormatProvider provider)
        {
            return "{" + this.x.ToString(provider) + "; " + this.y.ToString(provider) + "}";
        }
    }
}